import MenuModel from "../../schema/menu";
import ButtonModel from "../../schema/button";
import type Typings from "../../typings";
import axios from "axios";

// Mongoose 类的实例
import MongooseController from "../mongoose/mongoose";
const MenuModelIns = new MongooseController(MenuModel);
const ButtonModelIns = new MongooseController(ButtonModel);

// response 响应类型类的实例
import ResController from "../res/res";
const ResIns = new ResController();

class MenuController {
  constructor() {}

  // 递归获取菜单
  static async recursion(
    query: Typings.Common.plainObj = {},
    hasPermissionKeys?: string[]
  ): Promise<Typings.Menu.props[]> {
    const searchQuery = {
      $and: [query],
    };

    // hasPermissionKeys 参数不为 undefined 时，需要加入到查询参数中
    if (Array.isArray(hasPermissionKeys)) {
      searchQuery.$and.push({
        key: { $in: hasPermissionKeys },
      });
    }

    const data: Typings.Menu.props[] = await MenuModelIns.Find(searchQuery);

    for (let i = 0, len = data.length; i < len; i++) {
      const children = await MenuController.recursion(
        {
          parentKey: data[i].key,
        },
        hasPermissionKeys
      );

      data.splice(i, 1, {
        ...JSON.parse(JSON.stringify(data[i])),
        children,
      });

      if (!data[i].children?.length) {
        const buttonList = await ButtonModelIns.Find({
          parentKey: data[i].key,
        });
        data.splice(i, 1, {
          ...JSON.parse(JSON.stringify(data[i])),
          buttonList,
        });
      }
    }

    return data;
  }

  // allTree 带有按钮信息
  static async recursionAllTree(
    query: Typings.Common.plainObj = {}
  ): Promise<Typings.Menu.props[]> {
    const searchQuery = {
      ...query,
    };

    const data: Typings.Menu.props[] = await MenuModelIns.Find(searchQuery);

    for (let i = 0, len = data.length; i < len; i++) {
      const children = await MenuController.recursionAllTree({
        parentKey: data[i].key,
      });

      data.splice(i, 1, {
        ...JSON.parse(JSON.stringify(data[i])),
        children,
      });

      if (!data[i].children?.length) {
        const buttonList = await ButtonModelIns.Find({
          parentKey: data[i].key,
        });
        data.splice(i, 1, {
          ...JSON.parse(JSON.stringify(data[i])),
          buttonList,
        });
      }
    }

    return data;
  }

  // 菜单树（所有数据，不涉及权限）
  async allTree(req: Typings.Express.Request, res: Typings.Express.Response) {
    const data = await MenuController.recursionAllTree({ parentKey: "" });
    ResIns.Success(res, data);
  }

  // 菜单树（涉及权限）
  async tree(req: Typings.Express.Request, res: Typings.Express.Response) {
    const loginUserId = MenuModelIns.GetUserId(
      req as Typings.Express.ConvertRequest
    );

    const { systemName = "" } = req.query;

    const userInfo = await axios.get("http://127.0.0.1:8888/api/user/check", {
      params: { id: loginUserId },
      headers: req.headers,
    });

    const roleId = userInfo.data.data.roleId;

    const roleInfo = await axios.get(
      "http://127.0.0.1:8888/api/role/checkByRoleId",
      {
        params: { roleId },
        headers: req.headers,
      }
    );

    const { permissionKey, halfPermissionKey } = roleInfo.data.data;

    const hasPermissionKeys = [...permissionKey, ...halfPermissionKey];

    const data = await MenuController.recursion(
      { parentKey: systemName || "" },
      hasPermissionKeys
    );
    ResIns.Success(res, data);
  }

  // 新增
  async add(req: Typings.Express.Request, res: Typings.Express.Response) {
    try {
      const { parentKey, key, title, path, icon } = req.body || {};

      const menu: Typings.Menu.props[] = await MenuModelIns.Find({
        key,
      });

      if (menu.length) {
        ResIns.isExist(res);
        return;
      }

      await MenuModelIns.SaveOne(req, {
        parentKey,
        key,
        title,
        path,
        icon,
      });

      ResIns.Success(res);
    } catch (err) {
      ResIns.Database(res, err);
    }
  }

  // 更新信息
  async update(req: Typings.Express.Request, res: Typings.Express.Response) {
    try {
      const { id, title, path, icon } =
        <Partial<Typings.Menu.props>>req.body || {};

      if (!id) {
        ResIns.paramsWrong(res);
        return;
      }

      const updateContent = {
        title,
        path,
        icon,
      };

      await MenuModelIns.UpdateOne({ id }, updateContent);
      ResIns.Success(res);
    } catch (err) {
      ResIns.Database(res, err);
    }
  }

  // 查看
  async check(req: Typings.Express.Request, res: Typings.Express.Response) {
    try {
      const { id } = req.query || {};

      if (!id) {
        ResIns.paramsWrong(res);
        return;
      }

      // 查询数据
      const menus: Typings.Menu.props[] = await MenuModelIns.Find({
        id,
      });

      if (!menus.length) {
        // 不存在
        ResIns.isNotExist(res);
        return;
      }

      // 存在时
      ResIns.Success(res, menus[0]);
    } catch (err) {
      ResIns.Database(res, err);
    }
  }

  // 删除
  async remove(req: Typings.Express.Request, res: Typings.Express.Response) {
    try {
      let { id } = req.query || {};

      if (!id) {
        ResIns.paramsWrong(res);
        return;
      }

      const idMenu = await MenuModelIns.Find({ id });

      if (idMenu?.length) {
        const { key } = idMenu[0];
        const hasChildren = await MenuModelIns.Find({ parentKey: key });
        if (hasChildren?.length) {
          ResIns.Abnormal(res, "存在子节点|菜单，请先删除");
          return;
        }
      }

      // 删除数据
      await MenuModelIns.RemoveOne({ id });

      ResIns.Success(res);
    } catch (err) {
      ResIns.Database(res, err);
    }
  }
}

export default MenuController;
